/*
 * Copyright (c) 2010, Michael Hengler (developer (at) hengler (dot) de),
 * Nikolaus Moll (developer (at) miblounge (dot) net).
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * * Neither the name of the Jombi project nor the
 * names of its contributors may be used to endorse or promote products
 * derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL JOMBI BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */
package net.miblounge.jombi.impl.widgets;

import net.miblounge.jombi.impl.image.QtImageRegistry;
import net.miblounge.jombi.impl.util.BorderUtil;
import net.miblounge.jombi.impl.util.ColorConvert;
import net.miblounge.jombi.impl.util.DimensionConvert;
import net.miblounge.jombi.impl.util.PositionConvert;

import org.jowidgets.common.color.IColorConstant;
import org.jowidgets.common.image.IImageConstant;
import org.jowidgets.common.types.Dimension;
import org.jowidgets.common.types.Position;
import org.jowidgets.common.types.Rectangle;
import org.jowidgets.common.widgets.IDisplayCommon;
import org.jowidgets.common.widgets.controller.IWindowListener;
import org.jowidgets.common.widgets.descriptor.IWidgetDescriptor;
import org.jowidgets.common.widgets.factory.IGenericWidgetFactory;
import org.jowidgets.spi.impl.controller.WindowObservable;
import org.jowidgets.spi.widgets.IWindowSpi;

import com.trolltech.qt.core.QEvent;
import com.trolltech.qt.core.QEvent.Type;
import com.trolltech.qt.core.QObject;
import com.trolltech.qt.core.Qt;
import com.trolltech.qt.gui.QApplication;
import com.trolltech.qt.gui.QPalette;
import com.trolltech.qt.gui.QPalette.ColorRole;
import com.trolltech.qt.gui.QWidget;

public class QtWindow extends QtContainer implements IWindowSpi {

	private final WindowObservable windowObservableDelegate;
	private final ColorRole backgroundColorRole = ColorRole.Window;

	public QtWindow(final IGenericWidgetFactory factory, final QWidget window) {
		super(factory, window);

		this.windowObservableDelegate = new WindowObservable();

		// Register events
		getUiReference().installEventFilter(new QObject() {
			@Override
			public boolean eventFilter(final QObject sender, final QEvent e) {
				if (e.type() == Type.WindowActivate) {
					windowObservableDelegate.fireWindowActivated();
				}
				if (e.type() == Type.WindowDeactivate) {
					windowObservableDelegate.fireWindowDeactivated();
				}
				if (e.type() == Type.Show) {
					windowObservableDelegate.fireWindowDeiconified();
				}
				if (e.type() == Type.Hide) {
					windowObservableDelegate.fireWindowIconified();
				}
				return super.eventFilter(sender, e);
			}
		});
	}

	@Override
	public void pack() {
		// Qt's layout managers don't work on invisible widgets, so pretend visibility
		if (!isVisible()) {
			getUiReference().setAttribute(Qt.WidgetAttribute.WA_DontShowOnScreen, true);
			getUiReference().show();
			getUiReference().adjustSize();
			getUiReference().hide();
			getUiReference().setAttribute(Qt.WidgetAttribute.WA_DontShowOnScreen, false);
		} else {
			getUiReference().adjustSize();
		}
	}

	@Override
	public void setVisible(final boolean visible) {
		getUiReference().setVisible(visible);
	}

	@Override
	public boolean isVisible() {
		return getUiReference().isVisible();
	}

	@Override
	public void setPosition(final Position position) {
		final int x = position.getX() + BorderUtil.getBorderLeft();
		final int y = position.getY() + BorderUtil.getBorderTop();
		final int w = getUiReference().width();
		final int h = getUiReference().height();

		getUiReference().setGeometry(x, y, w, h);
	}

	@Override
	public Position getPosition() {
		return new Position(getUiReference().x(), getUiReference().y());
	}

	@Override
	public void setSize(final Dimension size) {
		final int x = getUiReference().x();
		final int y = getUiReference().y();

		// setGeometry sets the client area, so subtract the border size
		getUiReference().setGeometry(
				x,
				y,
				size.getWidth() - BorderUtil.getBorderWidth(),
				size.getHeight() - BorderUtil.getBorderHeight());
	}

	@Override
	public Dimension getSize() {
		return new Dimension(getUiReference().size().width() + BorderUtil.getBorderWidth(), getUiReference().size().height()
			+ BorderUtil.getBorderHeight());
	}

	@Override
	public <WIDGET_TYPE extends IDisplayCommon, DESCRIPTOR_TYPE extends IWidgetDescriptor<? extends WIDGET_TYPE>> WIDGET_TYPE createChildWindow(
		final DESCRIPTOR_TYPE descriptor) {
		return getGenericWidgetFactory().create(getUiReference(), descriptor);
	}

	protected void setIcon(final IImageConstant icon, final QtImageRegistry imageRegistry) {
		getUiReference().setWindowIcon(imageRegistry.getImage(icon));
	}

	@Override
	public Rectangle getParentBounds() {
		Dimension parentSize;
		Position parentPosition = new Position(0, 0);
		if (getUiReference().parentWidget() != null) {
			parentPosition = PositionConvert.convert(getUiReference().parentWidget().pos());
			parentSize = DimensionConvert.convert(getUiReference().parentWidget().frameSize());
		} else {
			parentSize = DimensionConvert.convert(QApplication.desktop().screenGeometry().size());
		}
		return new Rectangle(parentPosition, parentSize);
	}

	@Override
	public void addWindowListener(final IWindowListener listener) {
		windowObservableDelegate.addWindowListener(listener);
	}

	@Override
	public void removeWindowListener(final IWindowListener listener) {
		windowObservableDelegate.removeWindowListener(listener);
	}

	// Qt fix
	@Override
	public void setBackgroundColor(final IColorConstant colorValue) {
		final QPalette palette = getUiReference().palette();
		palette.setColor(backgroundColorRole, ColorConvert.convert(colorValue));
		getUiReference().setPalette(palette);
	}

	@Override
	public IColorConstant getBackgroundColor() {
		return ColorConvert.convert(getUiReference().palette().color(backgroundColorRole));
	}

	@Override
	public void dispose() {
		//		// close all other child windows
		//		for (final QObject child : getUiReference().children()) {
		//			if (child instanceof QDialog) {
		//				final QDialog dlg = (QDialog) child;
		//				dlg.setWindowTitle("close");
		//				//dlg.setVisible(false);
		//				//dlg.close();
		//			}
		//		}

		getUiReference().close();
		// TODO: dispose?
	}

	public void setMinSize(final Dimension minSize) {
		getUiReference().setMinimumSize(DimensionConvert.convert(minSize));
	}
}
